﻿using System;
using System.Threading.Tasks;
using NLog;
using Quartz;
using Quartz.Impl;
using Raise.Workbench.Core;
using Topshelf;

namespace Raise.Workbench.Service {
    public class QuartzService : ServiceControl, IQuartzServer {
        private static readonly Logger Logger = LogManager.GetCurrentClassLogger(typeof(QuartzService));
        private ISchedulerFactory schedulerFactory;
        private IScheduler scheduler;

        /// <summary>
        /// 初始化<see cref ="QuartzService"/>类的实例
        /// </summary>
        public virtual async Task Initialize() {
            try {
                schedulerFactory = CreateSchedulerFactory();
                scheduler = await GetScheduler().ConfigureAwait(false);
            } catch(Exception e) {
                Logger.Error(e, e.Message);
                throw;
            }
        }

        /// <summary>
        /// 获取此服务器应与之一起运行的调度程序.
        /// </summary>
        /// <returns></returns>
	    protected virtual Task<IScheduler> GetScheduler() {
            return schedulerFactory.GetScheduler();
        }

        /// <summary>
        /// 返回当前的调度程序实例（通常在<see cref ="Initialize"/>中创建
        /// 使用<see cref ="GetScheduler"/> 方法）。
        /// </summary>
	    protected virtual IScheduler Scheduler => scheduler;

        /// <summary>
        /// 创建将作为此实例上所有调度程序的工厂的调度程序工厂
        /// </summary>
        /// <returns></returns>
        protected virtual ISchedulerFactory CreateSchedulerFactory() {
            //var jobConfig = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "CofnigJobs\\QuartzJobs.xml");
            //var properties = new NameValueCollection {
            //    ["quartz.plugin.triggHistory.type"] = "Quartz.Plugin.History.LoggingJobHistoryPlugin, Quartz.Plugins",
            //    ["quartz.plugin.jobInitializer.type"] = "Quartz.Plugin.Xml.XMLSchedulingDataProcessorPlugin, Quartz.Plugins",
            //    ["quartz.plugin.jobInitializer.fileNames"] = jobConfig,
            //    ["quartz.plugin.jobInitializer.failOnFileNotFound"] = "true",
            //    ["quartz.plugin.jobInitializer.scanInterval"] = "120"
            //};

            return new StdSchedulerFactory();
        }

        /// <summary>
        /// 启动此实例，委托给调度程序.
        /// </summary>
        public virtual void Start() {
            try {
                Logger.Info("调度服务启动开始");
                CreateJobs create = new CreateJobs();
                create.Create(scheduler);
                scheduler.Start();
                Logger.Info("调度服务启动成功");
            } catch(Exception ex) {
                Logger.Error(ex, "调度服务启动调动失败");
                throw;
            }
        }

        /// <summary>
        ///停止此实例，委托给调度程序。
        /// </summary>
        public virtual void Stop() {
            try {
                scheduler.Shutdown(true);
                Logger.Info("调度服务关闭完成");
            } catch(Exception ex) {
                Logger.Error(ex, "调度服务停止失败");
                throw;
            }
        }

        /// <summary>
        /// 执行与释放，释放或重置非托管资源相关的应用程序定义的任务。
        /// </summary>
	    public virtual void Dispose() {
            // no-op for now
        }

        /// <summary>
        /// 暂停调度程序中的所有活动.
        /// </summary>
	    public virtual void Pause() {
            scheduler.PauseAll();
        }

        /// <summary>
        /// 恢复服务中的所有活动
        /// </summary>
	    public void Resume() {
            scheduler.ResumeAll();
        }

        /// <summary>
        /// TopShelf的方法委托给 <see cref="Start()"/>.
        /// </summary>
        public bool Start(HostControl hostControl) {
            Start();
            return true;
        }

        /// <summary>
        /// TopShelf的方法委托给 <see cref="Stop()"/>.
        /// </summary>
        public bool Stop(HostControl hostControl) {
            Stop();
            return true;
        }

        /// <summary>
        /// TopShelf的方法委托给 <see cref="Pause()"/>.
        /// </summary>
        public bool Pause(HostControl hostControl) {
            Pause();
            return true;
        }

        /// <summary>
        /// TopShelf的方法委托给 <see cref="Resume()"/>.
        /// </summary>
        public bool Continue(HostControl hostControl) {
            Resume();
            return true;
        }
    }
}
